<template>
	<div class="menu-pane">
		<el-input v-model="filterText" :placeholder="translate('tips.inputKey')"/>
		<el-scrollbar>
			<el-tree ref="tree"
					 class="menu-tree"
					 :data="cloneData"
					 node-key="code"
					 default-expand-all
					 :filter-node-method="filterNode"
					 draggable
					 :props="{label:'name'}"
					 :allow-drop="allowDrop"
					 @node-drop="onDrop">
				<span slot-scope="{ node, data }" class="custom-tree-node" :class="!data.tid?'new':''">
					<el-row>
						<el-col :span="12">
							<template v-if="data.iconDefault">
								<el-image class="icon" :src="iconSrc(data.iconDefault)"><i slot="error"/></el-image>
							</template>
							<template v-else>
								<vab-icon :icon="data.iconFont||''" class="icon"/>
							</template>
							<span><b>{{ data.name }}</b>&nbsp;&nbsp;[{{ data.code }}]</span>
						</el-col>
						<el-col :span="12" style="text-align: right; padding-right: 30px">
							<el-link class="operation-btn" icon="el-icon-edit"
								 type="primary" @click.stop="edit(data)" v-auth="'sys:menu:saveOrUpdateSysMenu'">{{translate('button.edit')}}</el-link>
							<el-link v-if="!data.tid || data.type !== MenuTypeEnum.node" class="operation-btn" icon="el-icon-delete"
								 type="danger" @click.stop="deleteGroup(data)" v-auth="'sys:menu:saveOrUpdateSysMenu'">{{translate('button.delete')}}</el-link>
						</el-col>
					</el-row>
				</span>
			</el-tree>
		</el-scrollbar>
		<div class="footer-btn">
			<el-button size="medium" @click="expandAllNode(data,true)">{{translate('label.expandAll')}}</el-button>
			<el-button size="medium" @click="expandAllNode(data,false)">{{translate('label.closeAll')}}</el-button>
			<el-button type="primary" size="medium" @click="save" v-auth="'sys:menu:saveOrUpdateSysMenu'">
                {{translate('button.save')}}
			</el-button>
			<el-button type="warning" size="medium" @click="add" v-auth="'sys:menu:saveOrUpdateSysMenu'">
                {{translate('button.add')}}
			</el-button>
		</div>

		<!--新增编辑菜单-->
		<el-drawer :title="eventType==='edit'?translate('button.edit'):translate('button.add')"
				   :visible.sync="showAddEdit"
				   direction="rtl"
				   close-on-press-escape
				   custom-class="media-size"
				   :wrapperClosable="false">
			<menu-add-edit v-if="showAddEdit" :data="menuItem" :type="eventType" :deviceType="deviceType" @cancel="close" @success="success"/>
		</el-drawer>
	</div>
</template>
<script lang="ts">
import _ from 'lodash';
import {Component, Watch, Prop} from "vue-property-decorator";
import BaseVue from '@/common/base-vue'

import {baseURL} from '@/config';

import MenuMgtService from '@/views/system/menu-mgt/menu-mgt.service';
import MenuModel from "@/views/system/menu-mgt/model/menu.model";
import SaveMenuModel from "@/views/system/menu-mgt/model/save-menu.model";
import {MenuTypeEnum} from "@/common/enum/common.enum";

//新增编辑组件
import menuAddEdit from '@/views/system/menu-mgt/menu-add-edit';
import {ElTree} from "element-ui/types/tree";
import {ICON_API} from "@/layout/const/menu.const";
import {DeviceEnum} from "./enum/menu-mgt.enum";

@Component({components: {menuAddEdit}})
export default class menuPane extends BaseVue {

	/*菜单类型枚举*/
	private MenuTypeEnum=MenuTypeEnum;

	/*过滤输入文本*/
	private filterText = '';
	/*显示新增编辑弹窗*/
	private showAddEdit = false;
	private saveMenuData: SaveMenuModel = new SaveMenuModel();
	/*菜单模型*/
	private menuItem: MenuModel = new MenuModel();
	/*操作类型，新增还是编辑*/
	private eventType = '';
	/*克隆备份数据*/
	private cloneData = [];
	/*传入菜单数据*/
	@Prop(Array)
	private data;
	//平台类型
    @Prop({type:String, required: true})
	private deviceType:DeviceEnum;

    private $refs:{tree:ElTree<any, any>}

	@Watch('filterText', {deep: true})
	filterTextChange(val, old) {
		this.$refs.tree.filter(val);
	}
	@Watch('data', {deep: true})
	dataChange(val, old) {
		this.cloneData=_.cloneDeep(val);
		this.saveMenuData.deviceType = this.deviceType;
		this.saveMenuData.menuList=this.cloneData;
	}

	/**
	 *加载图片的远程地址
	 */
	get iconSrc() {
		return (key: string) => {
			return baseURL + ICON_API + key;
		}
	};

	/**
	 * 生命周期created
	 */
	private created() {
	};

	/**
	 * 生命周期mounted
	 */
	private mounted() {
	};

	/**
	 * 搜索过滤树
	 */
	private filterNode(value, data) {
		if (!value) return true;
		return data.name.indexOf(value) !== -1;
	}

	/**
	 * 新增菜单组
	 */
	private add() {
		this.eventType = 'add';
		this.showAddEdit = true;
	}

	/**
	 * 编辑事件
	 */
	private edit(data) {
		this.eventType = 'edit';
		this.menuItem = _.cloneDeep(data);
		this.showAddEdit = true;
	}

	/**
	 *保存
	 */
	private async save() {
		const loading = this.$loading({lock: true,text:this.translate('tips.saving')});
		MenuMgtService.saveMenu(this.saveMenuData).then(res => {
			if(res.status===200){
				this.$message.success(this.translate('label.saveSuccessRelogin'));
				this.$emit('success',this.saveMenuData)
			}
		}).finally(()=>{
			loading.close();
		});
	}

	/**
	 * 删除事件
	 */
	private deleteGroup(data, type) {
		this.$confirm('此操作将删除该菜单组，并释放组内子菜单至根节点', '提示', {
			cancelButtonClass: "btn-custom-cancel",
			confirmButtonText: this.translate('button.sure'),
			cancelButtonText: this.translate('button.cancel'),
			type: 'warning'
		}).then(() => {
			const allChildren = _.cloneDeep(this.freeChildren([data]));
			this.findIndexInTree(this.cloneData, data);
			allChildren.forEach(item => delete item.parentCode);
			this.cloneData = [...this.cloneData, ...allChildren];
		}).catch(() => {
		});
	}

	/**
	 * 释放子节点
	 */
	private freeChildren(data, resArray = []) {
		data.forEach(item => {
			if (item.type === MenuTypeEnum.node) {
				resArray.push(item);
			} else if (item.type === MenuTypeEnum.group && item.children && item.children.length) {
				this.freeChildren(item.children, resArray);
			}
		});
		return resArray;
	}

	private findIndexInTree(data, item) {
		for (let i = 0; i < data.length; i++) {
			if (data[i].code === item.code) {
				data.splice(i, 1);
				break;
			} else if (data[i].children && data[i].children.length) {
				this.findIndexInTree(data[i].children, item);
			}
		}
	}

	private allowDrop(draggingNode, dropNode, type) {
		// 不允许组拖到子菜单 不允许子菜单拖拽到子菜单
		if (draggingNode.data.type === MenuTypeEnum.group && dropNode.data.type === MenuTypeEnum.node && type === 'inner') {
			return false;
		} else {
			return !(draggingNode.data.type === MenuTypeEnum.node && dropNode.data.type === MenuTypeEnum.node && type === 'inner');
		}
	}

	/**
	 * 拖拽完树节点
	 */
	private onDrop(dropNode, targetNode) {
		if(!targetNode.data.parentCode) {
			dropNode.data.parentCode = null;
		}else if(targetNode.data.type===MenuTypeEnum.group) {
			dropNode.data.parentCode = targetNode.data.code;
		}else{
			dropNode.data.parentCode = targetNode.data.parentCode
		}
	}

	/**
	 * 展开所有
	 */
	private expandAllNode(data, flag) {
		data.filter(item => item.type === MenuTypeEnum.group).forEach(item => {
			const node = this.$refs.tree.getNode(item.code);
			node.expanded = flag;
			this.expandAllNode(node.childNodes, flag);
		});
	}

	/**
	 * 监听保存成功事件
	 */
	public success(){
		this.showAddEdit=false;
		this.$emit('success');
	}
	/**
	 * 关闭弹窗
	 */
	public close(){
		this.showAddEdit=false;
	}
};
</script>
<style lang="scss" scoped>
.el-drawer{
    .el-drawer__header{
        padding: 40px;
    }
}
.menu-pane {
	overflow: auto;

	.el-scrollbar__wrap {
		overflow-x: hidden;
	}

	.el-scrollbar {
		margin-top: 8px;
		border: 1px solid #d3d3d3;
        height: calc(100vh - 320px);
	}

	.menu-tree {
		/*border: 1px solid #ececec;*/
		margin: 1px;

		::v-deep.el-tree-node__content {
			height: 42px;
			border-bottom: 1px solid #eeeeee;
		}
		.icon{width: 24px;
			height: 24px;
			position: relative;
			top: 6px;
			margin-right: 5px;
			line-height: 20px;
			overflow: hidden;
			font-size: 20px;;
		}
		.custom-tree-node {
			font-size: 14px;
			padding-right: 8px;
			height: 34px;
			line-height: 34px;
			width: 100%;

			.operation-btn {
				margin-top: -3px;
				margin-left: 5px;

				&:first-of-type {
					margin-left: 15px;
				}
			}

			.tree-node-icon {
				margin-right: 5px;
			}

			&.new {
				color: $base-color-blue;
			}
		}
	}
	.footer-btn {
		padding: 20px 0 0 0;
        .el-button{
            border-radius: 6px;
            min-width: 88px;
        }
	}
}
:focus {
	outline: 0;
}
</style>
